<template>
  <div
    class="input input-bordered relative flex h-auto flex-wrap items-center gap-2 py-2"
  >
    <span
      class="rounded-btn flex items-center gap-1 bg-primary px-4 py-1 text-primary-content"
      v-for="i in selectedTags"
      :key="i.value"
    >
      <span>{{ i.label }}</span>
      <span
        class="icon-[uil--times] h-6 w-6 text-white"
        @click="removeTag(i)"
      />
    </span>
    <input
      class="w-20 border-none bg-transparent p-2 text-base-content outline-none"
      v-model="text"
      @keydown.prevent.enter="onTextEnter"
      @keydown.prevent.up="onKeyUpDown('ArrowUp')"
      @keydown.prevent.down="onKeyUpDown('ArrowDown')"
      @focus="showPopItems = true"
      @blur="onInputBlur"
    />
    <div
      v-show="showPopItems && items.length > 0"
      class="absolute left-0 top-[calc(100%+0.5rem)] z-10 h-60 w-full overflow-y-auto border-2 border-base-200 bg-base-100 p-2"
    >
      <ul>
        <li
          class="rounded-md p-2 px-4 hover:bg-secondary hover:text-secondary-content"
          v-for="(item, index) in items"
          :key="item.value"
          :class="{
            'bg-primary text-primary-content': index === selected,
          }"
          @click="onTagItemClick(item)"
        >
          {{ item.label }}
        </li>
      </ul>
    </div>
  </div>
</template>
<script setup lang="ts">
export interface TagData {
  label: string;
  value: any;
}

interface Props {
  modelValue?: any[];
  data: TagData[];
}
const props = defineProps<Props>();
const emit = defineEmits<{
  "update:modelValue": [value: any[]];
  newTag: [value: string];
}>();

const text = ref("");
const showPopItems = ref(false);
const selected = ref(-1);
// 选中标签集合：是 props.modelValue 的副本
const tags = ref<any[]>(props.modelValue ?? []);

watch(
  () => props.modelValue,
  (val) => {
    tags.value = val ?? [];
  },
);

const items = computed(() => {
  const result = props.data.filter(
    ({ value, label }) =>
      label.startsWith(text.value) && !tags.value.includes(value),
  );
  if (result.length > 0 && text.value.length > 0) showPopItems.value = true;
  // 选中第一个
  selected.value = result.length > 0 ? 0 : -1;
  return result;
});

const onTextEnter = () => {
  if (selected.value >= 0)
    emit("update:modelValue", [
      ...tags.value,
      items.value[selected.value].value,
    ]);
  else if (text.value) {
    // 新建标签
    emit("newTag", text.value);
  }

  showPopItems.value = false;
  text.value = "";
};

const removeTag = (tag: TagData) => {
  emit(
    "update:modelValue",
    tags.value.filter((i) => i != tag.value),
  );
};

const onKeyUpDown = (key: "ArrowUp" | "ArrowDown") => {
  if (items.value.length == 0) return;
  if (key == "ArrowUp")
    selected.value = selected.value == 0 ? 0 : selected.value - 1;
  else
    selected.value =
      selected.value == items.value.length - 1 ? 0 : selected.value + 1;
};

const onTagItemClick = (item: TagData) => {
  emit("update:modelValue", [...tags.value, item.value]);
  showPopItems.value = false;
  text.value = "";
};

const onInputBlur = () => {
  setTimeout(() => {
    showPopItems.value = false;
  }, 200);
};

const selectedTags = computed(() => {
  return props.modelValue?.map((i) => props.data.find((j) => j.value == i)!);
});
</script>
